
/* Copyright (c) 2016-2018 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef GENERATED_CODE
#define GENERATED_CODE

#include <fstream>
#include <cstdarg>

#include <stdint.h>

#include "Log.h"
#include "NanoLog.h"
/**
 * This header declares the structures generated by the NanoLog Preprocessor
 * for the NanoLog runtime compression thread and LogDecompressor to use.
 */

namespace GeneratedFunctions {
/**
 * Describes a log message found in the user sources by the original format
 * string provided, the file and line number of where the message occurred.
 */
struct LogMetadata {
  const char *fmtString;
  const char *fileName;
  uint32_t lineNumber;
  NanoLog::LogLevel logLevel;
};

/**
 * Size of the arrays below, defined by the number of unique LogIds in the
 * system. LogIds are assigned to each unique combination of log format string
 *  and filename/line number combination. The first valid id is 0 and the last
 * is (numLogIds-1).
 */
extern size_t numLogIds;

// Maps unique logIds to the metadata associated with the log (see LogMetadata)
extern struct LogMetadata logId2Metadata[];

/**
 * Map of unique logIds to the compression function that takes an
 * UncompressedEntry from the StagingBuffer and and compresses it to buffer
 * out.
 *
 * \param re
 *          Pointer to an UncomrpessedLogEntry within a StagingBuffer.
 * \param[out] out
 *          An output buffer to write the compressed log entry to
 *
 * \return
 *      The number of bytes written to *out
 */
extern ssize_t
(*compressFnArray[]) (NanoLogInternal::Log::UncompressedEntry *re, char *out);


/**
 * Map of unique logIds to functions which would decompress and print the
 * original log message to outputFd.
 *
 * Each function takes in a buffer pointer (whose next bytes point to the
 * "argData" section of a CompressedLogEntry), an outputFd to output the log
 * message to, and an optional aggregation function that takes in the same
 * arguments as the original NANO_LOG(...) invocation. For example, an valid
 * aggregation function for NANO_LOG("Hello World %d, %s\r\n, num, str) would
 * have a function signature of void "fn(const char *, int, const char*)".
 *
 * \param[in/out] in
 *      Character buffer who's next bytes contain the argument section of
 *      a CompressedLogEntry.
 * \param outputFd
 *      File descriptor to print the original log message to. Set to NULL for
 *      no output.
 * \param[optional] aggFn
 *      Optional va_arg-style function used to aggregate the results.
 *      Note: This API is intended for benchmarking only
 */
extern void
(*decompressAndPrintFnArray[]) (const char **in,
                                    FILE *outputFd,
                                    void (*aggFn)(const char*, ...));

/***
 * Writes the metadata needed by the decompressor to interpret logs generated by
 * the compressFn's to a buffer. If inserted in a log, the decompressor will
 * use this dictionary in lieu of the decompressAndPrintFnArray. This metadata
 * should appear after a Checkpoint in the log.
 *
 * \param buffer
 *      Location to write dictionary to
 * \param endOfBuffer
 *      The last valid byte of buffer
 *
 * \return
 *      The number of bytes written; a value of -1 indicates that the dictionary
 *      did not fit in the buffer and a larger one should be passed in.
 */
long int writeDictionary(char *buffer, char *endOfBuffer);

} // namespace GeneratedFunctions

#endif /* BUFFER_STUFFER */
